﻿//除最后的去雾结果外，其它显示正常，可能问题：类型转换时候数据溢出。
#include <iostream>
#include <string>
#include <sstream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>    
#include <opencv2/opencv.hpp> 

#define t1 t.at<uchar>(row, col) 

using namespace std;
using namespace cv;

Mat image2Dark(Mat image);
Mat image2Pers(Mat dst);

double Max_dark_channel_d1 = 0;

double w0 = 1;  //乘积因子用来保留一些雾，1时完全去雾
double t0 = 0.4;
double R = 1.28;	//最后去雾类型转换可能溢出
int main(int argc, const char** argv)            //程序主函数
{


	string filename = "fog.jpg";
	auto image = imread(filename);
	imshow("原始图像", image);

	Mat dst = image2Dark(image);
	imshow("dark channnel的图形", dst);

	Mat t = image2Pers(dst);
	imshow("透射率t的图形", t);

	for (int row = 0; row < dst.rows; row++)
	{
		for (int col = 0; col < dst.cols; col++)
		{
			t.at<uchar>(row, col) = max(double(t.at<uchar>(row, col)), t0);//max(double(t.at<uchar>(row, col)), t0);
		}
	}
	Mat j(image.size(), image.type());

	for (int row = 0; row < j.rows; row++)
	{
		for (int col = 0; col < j.cols; col++)
		{
			j.at<Vec3b>(row, col)[0] = R * (image.at<Vec3b>(row, col)[0] - (1 - double(t1))*Max_dark_channel_d1 / double(t1));
			j.at<Vec3b>(row, col)[1] = R * (image.at<Vec3b>(row, col)[1] - (1 - double(t1))*Max_dark_channel_d1 / double(t1));
			j.at<Vec3b>(row, col)[2] = R * (image.at<Vec3b>(row, col)[2] - (1 - double(t1))*Max_dark_channel_d1 / double(t1));
		}
	}
	imshow("去雾后", j);
	waitKey(0);
}

Mat image2Pers(Mat dst)
{
	int Max_dark_channel = dst.at<uchar>(0, 0);
	Mat t(dst.size(), dst.type());
	for (int row = 0; row < dst.rows; row++)
	{
		for (int col = 0; col < dst.cols; col++)
		{
			if (dst.at<uchar>(row, col) > Max_dark_channel)
				Max_dark_channel = dst.at<uchar>(row, col);
		}
	}
	double Max_dark_channel_d = double(Max_dark_channel);
	Max_dark_channel_d1 = Max_dark_channel_d;
	for (int row = 0; row < dst.rows; row++)
	{
		for (int col = 0; col < dst.cols; col++)
		{
			t.at<uchar>(row, col) = 255 * (1 - w0 * double(dst.at<uchar>(row, col)) / Max_dark_channel_d);
		}
	}

	return t;
}
Mat image2Dark(Mat image)
{
	int img_col = image.cols;
	int img_hight = image.rows;
	int img_dim = image.channels();	//通道数
	//建立单通道图层
	Mat dst(image.rows, image.cols, CV_8UC1, Scalar(0));
	//获取暗度图像
	for (int row = 0; row < img_hight; row++)
	{
		for (int col = 0; col < img_col; col++)
		{
			if (img_dim == 1)
			{
				int gray = image.at<uchar>(row, col);
				image.at<uchar>(row, col) = 255 - gray;
			}
			else if (img_dim == 3)
			{
				int	b = image.at<Vec3b>(row, col)[0];  //读取通道值
				int	g = image.at<Vec3b>(row, col)[1];
				int	r = image.at<Vec3b>(row, col)[2];

				dst.at<uchar>(row, col) = min(b, min(g, r));
			}
		}
	}
	return dst;
}